package com.trsj.lnsj.service;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import com.alibaba.fastjson.JSONObject;
import com.trsj.lnsj.common.DataResponse;
import com.trsj.lnsj.common.MsgStatus;
import com.trsj.lnsj.model.PayLog;
import com.trsj.lnsj.util.IpUtils;
import com.trsj.lnsj.util.ResponseHelper;

import weixin.popular.api.PayMchAPI;
import weixin.popular.bean.paymch.MchBaseResult;
import weixin.popular.bean.paymch.MchPayNotify;
import weixin.popular.bean.paymch.SecapiPayRefund;
import weixin.popular.bean.paymch.SecapiPayRefundResult;
import weixin.popular.bean.paymch.Unifiedorder;
import weixin.popular.bean.paymch.UnifiedorderResult;
import weixin.popular.client.LocalHttpClient;
import weixin.popular.util.PayUtil;
import weixin.popular.util.SignatureUtil;
import weixin.popular.util.XMLConverUtil;

/**
 * @description:微信支付JAVA-SDK: APP支付,退款
 * @author:jason
 */
@Service
public class WechatPayService {
    private static final Logger LOGGER = LoggerFactory.getLogger(WechatPayService.class);
    @Autowired
    private Environment env;
    
    /************ 微信开放平台配置  ***************/
    
    /** APPID */
    private static final String APPID = "wxeb6ae02895e409c9"; 
    
    /** 商户号 */
    private static final String MCH_ID = "1511921601";  
    
    /** 密钥 */
    private static final String PRIVATE_KEY = "bbce1f7492b448fd11c1049c00ecb9a0";//"zlnsjrty545764utyjfjhjhgjghkghkg";
    
    /** 用户订单支付结果异步通知url */
    private static final String NOTIFY_URL = "/api/user/wechatOrderNotify";
    
    /** 商户支付证书路径 */
    private static final String API_CLIENT_CERT_PATH = "/usr/local/cert/apiclient_cert.p12";

    /** 定义应答变量 */
    private String xml;
    
    // 加载商户支付证书文件;
    static {
        LocalHttpClient.initMchKeyStore(MCH_ID, API_CLIENT_CERT_PATH);
    }
    
    /**MchPayApp
     * @description:使用微信支付-APP支付方式-统一下单;
     * @return 支付参数,如果支付失败则返回null
     * @author:Fanhaojian
     */
    public DataResponse orderAppPay(PayLog payLog,HttpServletRequest request) {
        Unifiedorder unifiedorder = new Unifiedorder();
        payLog.setPayCode(generateUniqueOrderNo());

        /** APPID */
        unifiedorder.setAppid(APPID);
        
        /** 商户号 */
        unifiedorder.setMch_id(MCH_ID);
        
        /** 随机字符串 */
        unifiedorder.setNonce_str(UUID.randomUUID().toString().replaceAll("-", ""));
        
        /** 商品描述 */
        unifiedorder.setBody("付费活动");
        
        /** 商户订单号 */
        unifiedorder.setOut_trade_no(payLog.getPayCode());
        
        /** 订单总金额 */
        unifiedorder.setTotal_fee(payLog.getPayPrice()*(new BigDecimal(100)).intValue() + "");   // 订单总金额,单位为分;
        
        /** 用户端请求IP地址 */
        unifiedorder.setSpbill_create_ip(IpUtils.getIpAddr(request));
        
        /** 异步通知回调地址 */
        unifiedorder.setNotify_url(request.getRequestURL().toString().split("/api/")[0] + NOTIFY_URL);
        
        /** 交易类型 */
        unifiedorder.setTrade_type("APP");
        
        LOGGER.warn("微信APP支付--(签名前):" + XMLConverUtil.convertToXML(unifiedorder));
        
        /** 获取签名 */
        UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, PRIVATE_KEY);
        
        LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_code):" + unifiedorderResult.getReturn_code());
        LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_msg):" + unifiedorderResult.getReturn_msg());
        LOGGER.warn("微信APP支付--支付统一下单接口请求状态(result_code):" + unifiedorderResult.getResult_code());
        LOGGER.warn("微信APP支付--支付请求参数封装(签名后):" + XMLConverUtil.convertToXML(unifiedorder));
        LOGGER.warn("微信APP支付--支付统一下单接口返回数据:" + JSONObject.toJSONString(unifiedorderResult));
        
        // 下单结果验签; 
        if(unifiedorderResult.getSign_status() != null && unifiedorderResult.getSign_status()) {
            LOGGER.warn("微信APP支付验签成功");
            DataResponse res = ResponseHelper.getSuccessResponse(PayUtil.generateMchAppData(unifiedorderResult.getPrepay_id(), APPID, MCH_ID, PRIVATE_KEY));
            res.setMessage("微信APP支付验签成功");
        }
        return ResponseHelper.getResponse(MsgStatus.STATUS_FAILED, "微信APP支付验签失败");
    }

    /**
     * @description:微信退款业务封装(支付押金退还);
     * @param 　 PayLog order:支付订单信息
     *           Double refundAmount:退款金额
     * @return 微信退款接口返回数据  true 退款成功  false 退款失败
     * @author:FanHaoJian
     */
    public Boolean refundOrder(PayLog order, Double refundAmount) {
        //调用微信支付退款接口;
        SecapiPayRefund payRefund = new SecapiPayRefund();
        payRefund.setAppid(APPID);
        payRefund.setMch_id(MCH_ID);
        payRefund.setNonce_str(UUID.randomUUID().toString().replaceAll("-", ""));
        payRefund.setOut_trade_no(order.getPayCode());//支付订单号
        payRefund.setOut_refund_no(order.getRefundCode());//退款单号
        payRefund.setTotal_fee((int) (order.getPayPrice()*(new BigDecimal(100)).intValue()));//原订单金额,单位:分;
        payRefund.setRefund_fee(new BigDecimal(refundAmount).multiply(new BigDecimal(100)).intValue());//退款订单金额,单位:分;
        
        SecapiPayRefundResult refundResult = PayMchAPI.secapiPayRefund(payRefund, PRIVATE_KEY);
        
        // 微信支付退款接口返回数据验签;
        if(refundResult.getSign_status() != null && refundResult.getSign_status()) {
            LOGGER.warn("微信退款接口--接口请求状态(return_code):" + refundResult.getReturn_code());
            LOGGER.warn("微信退款接口--接口请求状态(return_msg):" + refundResult.getReturn_msg());
            
            // 退款信息提交成功;
            if("SUCCESS".equals(refundResult.getReturn_code())) {
                LOGGER.warn("微信退款接口--接口请求状态(result_code):" + refundResult.getResult_code());
                LOGGER.warn("微信退款接口--接口请求状态(err_code):" + refundResult.getErr_code());
                LOGGER.warn("微信退款接口--接口请求状态(err_code_des):" + refundResult.getErr_code_des());
                
                return Boolean.TRUE;
            }
        }
        
        return Boolean.FALSE;
    }

    /**
     * 微信支付异步通知请求URL
     * @param request
     * @return
     * @throws Exception
     */
    public DataResponse wechatOrderNotify(HttpServletRequest request) {
        
        // 解析微信支付异步通知请求参数;
        String xml = "";
        try {
            xml = StreamUtils.copyToString(request.getInputStream(), Charset.forName("utf-8"));
            Map<String, String> params = XMLConverUtil.convertToMap(xml);
            MchPayNotify payNotify = XMLConverUtil.convertToObject(MchPayNotify.class, xml);
            
            /** 打印日志信息 */
            LOGGER.warn("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$---进入微信支付异步通知请求接口---$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
            LOGGER.warn("微信支付用户订单支付结果异步通知请求参数(xml):" + params);
            LOGGER.warn("微信支付用户订单支付结果异步通知请求参数(map):" + params);
            LOGGER.warn("return_code:" + payNotify.getReturn_code());
            LOGGER.warn("return_msg:" + params.get("return_msg"));
            
            /** 校验支付成功还是失败 */
            if("SUCCESS".equals(payNotify.getReturn_code())) {
                
                /** 获取微信后台返回来的异步通知参数 */
                String outTradeNo = payNotify.getOut_trade_no();  // 用户订单号;
                String tradeNo = payNotify.getTransaction_id();   // 微信交易号;
                String tradeStatus = payNotify.getResult_code();  // 微信支付状态;
                Integer totalFee = payNotify.getTotal_fee();      // 支付金额
                
                /** 获取验签结果 true说明验签成功   false说明验签失败 */
                boolean flag = SignatureUtil.validateSign(params, PRIVATE_KEY);
                
                /** 打印日志信息 */
                LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知订单号(out_trade_no):" + outTradeNo);
                LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知交易号(trade_no):" + tradeNo);
                LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知交易状态(result_code):" + tradeStatus);
                LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知支付金额(total_fee):" + totalFee);
                LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知验签状态:" + flag);
                
                /** 根据订单号获取订单支付信息: 支付状态为 '未支付' */
                //此处省略 根据订单号去查订单 我用hibernate的 你们可能用mybatis或者其他,所以自己去查吧!
                
                /** 支付成功/处理订单业务信息 */
                if(flag && "SUCCESS".equals(tradeStatus)) {
                    
                    /** 更新订单支付信息: */
                    //此处省略 根据自己项目的业务去处理逻辑!
                    
                    /** 封装通知信息 */
                    MchBaseResult baseResult = new MchBaseResult();
                    baseResult.setReturn_code("SUCCESS");
                    baseResult.setReturn_msg("OK");
                    xml =  XMLConverUtil.convertToXML(baseResult);
                
                /** 支付成功 */
                }else if(flag && "SUCCESS".equals(tradeStatus)){
                    MchBaseResult baseResult = new MchBaseResult();
                    baseResult.setReturn_code("SUCCESS");
                    baseResult.setReturn_msg("OK");
                    xml =  XMLConverUtil.convertToXML(baseResult);
                
                /** 支付失败 */
                }else {    
                    MchBaseResult baseResult = new MchBaseResult();
                    baseResult.setReturn_code("FAIL");
                    baseResult.setReturn_msg("FAIL");
                    xml =  XMLConverUtil.convertToXML(baseResult);
                }
            
            /** 支付失败 */    
            }else {
                MchBaseResult baseResult = new MchBaseResult();
                baseResult.setReturn_code("FAIL");
                baseResult.setReturn_msg("FAIL");
                xml =  XMLConverUtil.convertToXML(baseResult);
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage());
            return ResponseHelper.getResponse(MsgStatus.STATUS_FAILED, "支付失败");
        }
        LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知返回数据:" + xml);
        DataResponse resp = ResponseHelper.getSuccessResponse(xml);
        return resp;
    }

    public String getXml() {
        return xml;
    }

    public void setXml(String xml) {
        this.xml = xml;
    }

    //生成商户网站唯一订单号
    private String generateUniqueOrderNo() {
        String rndStr = "KL" + "O" + UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
        String paymentID = rndStr.substring(0, 32);// 订单ID
        return paymentID;
    }
}
